import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;
import java.io.File;
import javax.imageio.ImageIO;
import java.awt.Graphics2D;
import java.awt.RenderingHints;

public class App {
    public static void main(String[] args) throws Exception {
        File inputFile = new File("D:\\testpng\\test002.png");
        BufferedImage image = ImageIO.read(inputFile);

        // 灰度化 + 二值化 + 裁剪 + 缩放
        BufferedImage grayImage = App.toGrayscaleImage(image);
        BufferedImage binaryImage = App.applyOtsuBinarization(grayImage);
        BufferedImage croppedImage = App.autoCropWithMargin(binaryImage, 10);
        BufferedImage resizedImage = App.resizeToWidth(croppedImage, 300);
        // 默认白色背景，将白色背景设为透明--可选
        BufferedImage transparentImage = App.makeBackgroundTransparent(resizedImage, java.awt.Color.WHITE.getRGB(), 10);
        File outputFile = new File("D:\\testpng\\new_test03.png");
        ImageIO.write(transparentImage, "png", outputFile);

        System.out.println("图像处理完成！");
    }

    // 灰度化优化：使用 Raster
    public static BufferedImage toGrayscaleImage(BufferedImage originalImage) {
        int width = originalImage.getWidth();
        int height = originalImage.getHeight();

        BufferedImage grayImage = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
        WritableRaster raster = (WritableRaster) grayImage.getRaster();

        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                int rgb = originalImage.getRGB(x, y);
                int r = (rgb >> 16) & 0xff;
                int g = (rgb >> 8) & 0xff;
                int b = rgb & 0xff;
                int gray = (int) (0.3 * r + 0.59 * g + 0.11 * b);
                raster.setSample(x, y, 0, gray);
            }
        }

        return grayImage;
    }

    // 二值化优化：合并灰度和阈值判断
    public static BufferedImage applyOtsuBinarization(BufferedImage grayImage) {
        int width = grayImage.getWidth();
        int height = grayImage.getHeight();

        // 构建直方图
        int[] histogram = new int[256];
        WritableRaster raster = (WritableRaster) grayImage.getRaster();
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                int gray = raster.getSample(x, y, 0);
                histogram[gray]++;
            }
        }

        int threshold = ThresholdCalculator.otsuThreshold(histogram);

        BufferedImage binaryImage = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_BINARY);
        WritableRaster binaryRaster = (WritableRaster) binaryImage.getRaster();

        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                int gray = raster.getSample(x, y, 0);
                binaryRaster.setSample(x, y, 0, (gray <= threshold) ? 0 : 255);
            }
        }

        return binaryImage;
    }

    // 裁剪优化：避免多次 getRGB
    public static BufferedImage autoCropWithMargin(BufferedImage image, int margin) {
        int width = image.getWidth();
        int height = image.getHeight();
        WritableRaster raster = (WritableRaster) image.getRaster();

        int minX = width, minY = height, maxX = -1, maxY = -1;

        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                if (raster.getSample(x, y, 0) == 0) { // 黑色像素
                    minX = Math.min(minX, x);
                    minY = Math.min(minY, y);
                    maxX = Math.max(maxX, x);
                    maxY = Math.max(maxY, y);
                }
            }
        }

        minX = Math.max(0, minX - margin);
        minY = Math.max(0, minY - margin);
        maxX = Math.min(width - 1, maxX + margin);
        maxY = Math.min(height - 1, maxY + margin);

        if (maxX <= minX || maxY <= minY) {
            return new BufferedImage(1, 1, BufferedImage.TYPE_BYTE_BINARY);
        }

        return image.getSubimage(minX, minY, maxX - minX + 1, maxY - minY + 1);
    }

    // 4. 缩放优化：使用 RescaleOp 或 AffineTransform
    public static BufferedImage resizeToWidth(BufferedImage originalImage, int targetWidth) {
        int originalWidth = originalImage.getWidth();
        int originalHeight = originalImage.getHeight();
        int targetHeight = (int) (originalHeight * ((double) targetWidth / originalWidth));

        BufferedImage resizedImage = new BufferedImage(targetWidth, targetHeight, originalImage.getType());
        Graphics2D g2d = resizedImage.createGraphics();
        g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        g2d.drawImage(originalImage, 0, 0, targetWidth, targetHeight, null);
        g2d.dispose();

        return resizedImage;
    }

    /**
     * 将指定颜色的背景设为透明
     *
     * @param image     输入图像（建议为灰度或 RGB）
     * @param bgColor   背景颜色（int形式，如 Color.WHITE.getRGB()）
     * @param tolerance 容差（允许的色差范围，适用于抗锯齿边缘）
     * @return 带透明背景的新图像
     */
    public static BufferedImage makeBackgroundTransparent(BufferedImage image, int bgColor, int tolerance) {
        int width = image.getWidth();
        int height = image.getHeight();

        BufferedImage result = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        WritableRaster raster = (WritableRaster) image.getRaster();

        int rBg = (bgColor >> 16) & 0xff;
        int gBg = (bgColor >> 8) & 0xff;
        int bBg = bgColor & 0xff;

        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                int rgb = image.getRGB(x, y);
                int r = (rgb >> 16) & 0xff;
                int g = (rgb >> 8) & 0xff;
                int b = rgb & 0xff;

                // 判断是否为背景色
                if (Math.abs(r - rBg) <= tolerance &&
                        Math.abs(g - gBg) <= tolerance &&
                        Math.abs(b - bBg) <= tolerance) {
                    // 设置为透明
                    result.setRGB(x, y, 0x00000000);
                } else {
                    // 保留原色
                    result.setRGB(x, y, rgb);
                }
            }
        }

        return result;
    }
}
